#include "InterOpAttributeHelper.h"

#include "at_str.hxx"
#include "at_wstr.hxx"
#include "at_int.hxx"
#include "api.hxx"
#include "ga_api.hxx"
#include "rgbcolor.hxx"
#include "common/logger.h"
#include "rnd_api.hxx"
#include "collection.hxx"
#include "at_real.hxx"

AMCAX_EXCHANGE_NAMESPACE_BEGIN

const int MAX_FILE_NAME_CHARS = 512;  // For supporting filepath having greater length than 256 character.(IR 408636)
 
namespace InterOp {

bool CopyToMBCS( const wchar_t * ipwszStr, char *& opszStr)
{
    if ( NULL == ipwszStr )
        return false;
    size_t wideLen = wcslen( ipwszStr );
    size_t mbcsLen = wcstombs( NULL, ipwszStr, 2 * ( wideLen + 1));
    opszStr = new char[ mbcsLen + 1];
    size_t len = wcstombs( opszStr, ipwszStr, mbcsLen + 1);
    bool ok = ( (mbcsLen -1) != len);
    return ok;
}
 
bool DumpNameAttribute(ENTITY* iEnt)
{
	ATTRIB_GEN_NAME* pNameAttrib = NULL;					
	ATTRIB_GEN_STRING* label_attrib=NULL;
	ATTRIB_GEN_WSTRING* label_attrib_wchar=NULL;	

	outcome	resul = api_find_named_attribute( iEnt, "ATTRIB_XACIS_NAME", reinterpret_cast< ATTRIB_GEN_NAME*&>( pNameAttrib ) );
   	
	if( !pNameAttrib)
		resul = api_find_named_attribute( iEnt, "ATTRIB_NAME", reinterpret_cast< ATTRIB_GEN_NAME*&>( pNameAttrib ) );

	if (pNameAttrib )
	{
		if(is_ATTRIB_GEN_WSTRING(pNameAttrib))
		{
			label_attrib_wchar = (ATTRIB_GEN_WSTRING*)pNameAttrib;
			wchar_t* name=(wchar_t*)label_attrib_wchar->value();

			#ifdef _WINDOWS_SOURCE
				fwprintf(fp, L"\nATTRIB_XACIS_NAME : %s", name);
			#else
				char* pWord = NULL;
				CopyToMBCS( name, pWord );
                // LOG_DEBUG("ATTRIB_XACIS_NAME: {}", pWord); 
				delete [] pWord;
				pWord = NULL;
			#endif
		}
		else
		{
			label_attrib = (ATTRIB_GEN_STRING*)pNameAttrib;
			const char* name=label_attrib->value();
			// LOG_DEBUG("ATTRIB_XACIS_NAME : {}",name);
		}

		return true;
	}
	return false;
}

 //ID
 bool DumpIdAttribute(ENTITY* iEn)
 {
     ATTRIB_GEN_STRING* pId = NULL;
     outcome	resul = api_find_named_attribute( iEn, "ATTRIB_XACIS_ID", reinterpret_cast< ATTRIB_GEN_NAME*&>( pId) );
        
     char* pTempId = NULL;
     if( pId && ( resul.ok() == TRUE))
     {
         ATTRIB_GEN_WSTRING* label_attrib_wchar=NULL;	
 
         if(is_ATTRIB_GEN_WSTRING(pId))
         {
             label_attrib_wchar = (ATTRIB_GEN_WSTRING*)pId;
             wchar_t* name=(wchar_t*)label_attrib_wchar->value();
 #ifdef _WINDOWS_SOURCE
             fwprintf(fp, L"\nATTRIB_XACIS_ID : %s", name);
 #else
             char* pWord = NULL;
             CopyToMBCS(name, pWord);
            //  LOG_DEBUG( "ATTRIB_XACIS_ID : {}", pWord);
             delete[] pWord;
             pWord = NULL;
 #endif
             return true;
         }
         else
         {
             const char* pTmpStr = pId->value();
             if( pTmpStr && ( resul.ok() == TRUE))
             {
                 pTempId = new char [ strlen(pTmpStr) + 1];
                 strcpy(pTempId, pTmpStr);
                //  LOG_DEBUG("ATTRIB_XACIS_ID : {}", pTempId);
                 if (NULL != pTempId)
                 {
                     delete[] pTempId;
                     pTempId = NULL;
                 }
                 return true;
             }
         }
     }
 
     return false;
 }


 //Show
bool DumpShowAttribute( ENTITY* ipEnt)
{
	ATTRIB_GEN_INTEGER* pShow = NULL;
	outcome result = api_find_named_attribute( ipEnt, "ATTRIB_XACIS_SHOW", reinterpret_cast< ATTRIB_GEN_NAME*&>( pShow) );

	if( result.ok() == TRUE)
	{
		if (NULL != pShow)
		{
			LOG_DEBUG("ATTRIB_XACIS_SHOW : {}",pShow->value());
		}
		return true;
	}
	return false;
}

bool DumpPNAMEAttribute(ENTITY* iEnt)
{
	bool gotPName = false;
	const char* pPNameID = "ATTRIB_XACIS_PNAME";
	ATTRIB_GEN_NAME* pPNameAttrib = find_named_attrib( iEnt, pPNameID ); 
	while( NULL != pPNameAttrib )
	{
		gotPName = DumpSinglePNAMEAttribute( pPNameAttrib );
		pPNameAttrib = find_next_named_attrib( pPNameAttrib );
	}

	return gotPName;
}

bool DumpSinglePNAMEAttribute( ATTRIB_GEN_NAME* ipAttrib )
{
	if( NULL != ipAttrib  )
	{
		if( is_ATTRIB_GEN_WSTRING( ipAttrib ) )
		{
			ATTRIB_GEN_WSTRING* pAttribWChar = (ATTRIB_GEN_WSTRING*)ipAttrib;
			wchar_t* pPName=(wchar_t*)pAttribWChar->value();

			#ifdef _WINDOWS_SOURCE
				fwprintf( ipFilePointer, L"\nATTRIB_XACIS_PNAME : %s", pPName );
			#else
				char* pWord = NULL;
				CopyToMBCS( pPName, pWord );
				LOG_DEBUG("ATTRIB_XACIS_PNAME : {}", pWord );
				delete [] pWord;
				pWord = NULL;
			#endif
		}
		else
		{
			ATTRIB_GEN_STRING* pAttribChar = (ATTRIB_GEN_STRING*)ipAttrib;
			const char* pPName = pAttribChar->value();
			LOG_DEBUG("ATTRIB_XACIS_PNAME : {}",pPName );
		}

		return true;
	}
	return false;
}

bool DumpPIDAttribute(ENTITY* iEnt)
{
	bool gotPId = false;
	const char* pPIdID = "ATTRIB_XACIS_PID";
	ATTRIB_GEN_NAME* pPIdAttrib = find_named_attrib( iEnt, pPIdID ); 
	while( NULL != pPIdAttrib )
	{
		gotPId = DumpSinglePIDAttribute( pPIdAttrib);
		pPIdAttrib = find_next_named_attrib( pPIdAttrib );
	}

	return gotPId;
}

bool DumpSinglePIDAttribute( ATTRIB_GEN_NAME* ipAttrib)
{
	if( NULL != ipAttrib )
	{
		if( is_ATTRIB_GEN_WSTRING( ipAttrib ) )
		{
			ATTRIB_GEN_WSTRING* pAttribWChar = (ATTRIB_GEN_WSTRING*)ipAttrib;
			wchar_t* pPId=(wchar_t*)pAttribWChar->value();

			#ifdef _WINDOWS_SOURCE
				fwprintf( ipFilePointer, L"\nATTRIB_XACIS_PID : %s", pPId );
			#else
				char* pWord = NULL;
				CopyToMBCS( pPId, pWord );
				LOG_DEBUG("ATTRIB_XACIS_PID : {}", pWord );
				delete [] pWord;
				pWord = NULL;
			#endif
		}
		else
		{
			ATTRIB_GEN_STRING* pAttribChar = (ATTRIB_GEN_STRING*)ipAttrib;
			const char* pPId = pAttribChar->value();
			LOG_DEBUG("ATTRIB_XACIS_PID : {}", pPId );
		}

		return true;
	}
	return false;
}

//Alias
bool DumpAliasAttribute( ENTITY* ipEnt)
{
	ATTRIB_GEN_NAME* pAlias = NULL;
	ATTRIB_GEN_STRING* pAlias_attrib=NULL;
	ATTRIB_GEN_WSTRING* pAlias_attrib_wchar=NULL;
	outcome	result = api_find_named_attribute( ipEnt, "ATTRIB_XACIS_ALIAS", pAlias );
	
	if( NULL == pAlias || ( result.ok() != TRUE))
		return false;

	while( pAlias)
	{
		if(is_ATTRIB_GEN_WSTRING(pAlias))
		{
			pAlias_attrib_wchar = (ATTRIB_GEN_WSTRING*)pAlias;
			const wchar_t* pwAlias=(const wchar_t*)pAlias_attrib_wchar->value();

			#ifdef _WINDOWS_SOURCE
				fwprintf(fp, L"\nATTRIB_XACIS_ALIAS : %s", pwAlias);
			#else
				char* pWord = NULL;
				CopyToMBCS( pwAlias, pWord );
				LOG_DEBUG("ATTRIB_XACIS_ALIAS : {}",pWord);
				delete [] pWord;
				pWord = NULL;
			#endif
		}
		else
		{
			pAlias_attrib = (ATTRIB_GEN_STRING*)pAlias;
			const char* pTmpStr = pAlias_attrib->value();
			if( pTmpStr)
			{
				LOG_DEBUG("ATTRIB_XACIS_ALIAS : {}",pTmpStr);
			}
		}

		ATTRIB_GEN_NAME* pAlias2 = find_next_named_attrib (pAlias);
		pAlias = pAlias2;
	}
 	return true;
}

//Workplane
bool DumpPlaneAttribute( ENTITY* ipEnt)
{
	ATTRIB_GEN_INTEGER* pPlane = NULL;
	outcome result = api_find_named_attribute( ipEnt, "SPAATTRIB_UNBOUNDED_PLANE", reinterpret_cast< ATTRIB_GEN_NAME*&>( pPlane ) );
	
	if( result.ok() == TRUE && NULL != pPlane)
	{
		int oPlane = pPlane->value() ;
		LOG_DEBUG("SPAATTRIB_UNBOUNDED_PLANE : {}",oPlane);
		
		return true;
	}
	return false;
}

bool DumpAxisAttribute( ENTITY* ipEnt)
{
	ATTRIB_GEN_INTEGER* pAxis = NULL;
	outcome result = api_find_named_attribute( ipEnt, "SPAATTRIB_UNBOUNDED_AXIS", reinterpret_cast< ATTRIB_GEN_NAME*&>( pAxis ) );
	
	if( result.ok() == TRUE && NULL != pAxis)
	{
		int oAxis = pAxis->value() ;
		LOG_DEBUG("SPAATTRIB_UNBOUNDED_AXIS : {}",oAxis);
		
		return true;
	}
	return false;
}

//Color and Transparency
bool DumpColorAttribute(ENTITY* iEnt)
{
	rgb_color rgb;
	int found = 0;
	bool result = false;
	outcome	resul = api_rh_get_entity_rgb(iEnt, rgb, true, found);
	
	if(resul.ok() == TRUE)
	{
		// LOG_DEBUG("ATTRIB_RGB : {}  {}  {}",rgb.red(),rgb.green(),rgb.blue());
		result = true;
	}
	result = DumpTransparencyAttribute(iEnt);
  	return true;
}

//Transparency
bool DumpTransparencyAttribute(ENTITY* iEnt)
{
	double transp = -1.0;
	int found = 0;
	outcome	resul = api_rh_get_material_transp(iEnt, transp);
	
	if(resul.ok() == TRUE)
	{
		// LOG_DEBUG("ATTRIB_TRANSPARENCY : %f ", transp);
		return true;
	}
  	return true;
}

//LayerNumber
bool DumpLayerNumberAttribute( ENTITY* ipEnt)
{
	ATTRIB_GEN_INTEGER* layer_attrib = NULL;
	outcome result = api_find_named_attribute( ipEnt, "SPAX_LAYER", reinterpret_cast< ATTRIB_GEN_NAME*&>(  layer_attrib) );

	if (NULL == layer_attrib)
	{
		result = api_find_named_attribute( ipEnt, "ATTRIB_XACIS_LAYER", reinterpret_cast< ATTRIB_GEN_NAME*&>(  layer_attrib) );
	}
	
	if( layer_attrib )
	{
		int oLayer= layer_attrib->value();
		LOG_DEBUG("ATTRIB_XACIS_LAYER : {}",oLayer);
		return true;
	}
	return false;
}

//LayerName
bool DumpLayerNameAttribute( ENTITY* ipEnt)
{
	ATTRIB_GEN_STRING* layer_attrib = NULL;
	ATTRIB_GEN_WSTRING* layer_attrib_wchar = NULL;
	outcome result = api_find_named_attribute( ipEnt, "SPAX_LAYER_NAME", reinterpret_cast< ATTRIB_GEN_NAME*&>(  layer_attrib) );

	if (NULL == layer_attrib)
	{
		result = api_find_named_attribute( ipEnt, "ATTRIB_XACIS_LAYER_NAME", reinterpret_cast< ATTRIB_GEN_NAME*&>(  layer_attrib) );
	}
	
	if( layer_attrib )
	{
		if (is_ATTRIB_GEN_WSTRING(layer_attrib))
		{
			layer_attrib_wchar = (ATTRIB_GEN_WSTRING*)layer_attrib;
			wchar_t* name = (wchar_t*)layer_attrib_wchar->value();

			#ifdef _WINDOWS_SOURCE
				fwprintf(fp, L"\nATTRIB_XACIS_LAYER_NAME : %s", name);
			#else
				char* pWord = NULL;
				CopyToMBCS(name, pWord);
				LOG_DEBUG( "ATTRIB_XACIS_LAYER_NAME : %s", pWord);
				delete[] pWord;
				pWord = NULL;
			#endif
		}
		else
		{
			const char* oLayer = layer_attrib->value();
			LOG_DEBUG("ATTRIB_XACIS_LAYER_NAME : %s", oLayer);
		}
		return true;
	}
	return false ;
}

//Type 7 MaterialProperty 
bool DumpMaterialProperty( ENTITY* ipEnt)
{
	ATTRIB_GEN_INTEGER* pMatProp = NULL;
	outcome result = api_find_named_attribute( ipEnt, "ATTRIB_XACIS_GROUP_TYPE", reinterpret_cast< ATTRIB_GEN_NAME*&>( pMatProp ) );

	if( result.ok() == TRUE && NULL != pMatProp )
	{
		int oProp = pMatProp->value();
		if(oProp == 7)
		{
			LOG_DEBUG("ATTRIB_XACIS_GROUP_TYPE : SPAXAcisGroupTypeMaterialProperty [7]");
			
			size_t convertedChars = -1;
			ATTRIB_GEN_WSTRING * param_attrib_material_name = NULL;
			char matName[MAX_FILE_NAME_CHARS]="";
			const char * attName = "SPAATTRIB_MATERIAL_NAME";
			//getting label for the given collection it is material name for material property collection
			result = api_find_named_attribute( ipEnt, attName, (ATTRIB_GEN_NAME*&)(param_attrib_material_name ) );
 			
			if(param_attrib_material_name != 0)
				convertedChars = wcstombs( matName,  (wchar_t *)(param_attrib_material_name->value()), MAX_FILE_NAME_CHARS );
			if(convertedChars != -1)
				LOG_DEBUG("Material Name :  \t%s",matName);

			SPACOLLECTION* matCollection = (SPACOLLECTION*)ipEnt; //getting the collection
			if(matCollection != 0)
			{
				matCollection ->init(); //initializing the collection
				ENTITY* iEntity = NULL;
 
				while( (iEntity = matCollection ->next()) != NULL) //traverse through all the members of the collection
				{
					////for getting the property name like SPAATTRIB_MATERIAL_DENSITY,SPAATTRIB_MATERIAL_YOUNG_MODULUS etc.  
					DumpNameAttribute(iEntity);

					ATTRIB_GEN_REAL * param_attrib_value = NULL;
					const char * attValue = "SPAATTRIB_VALUE";
					//for getting the property value in double format.
					result = api_find_named_attribute( iEntity, attValue, (ATTRIB_GEN_NAME*&)(param_attrib_value) );
 						if(param_attrib_value != 0)
 					LOG_DEBUG("\t\t %f",param_attrib_value->value());

					ATTRIB_GEN_STRING * param_attrib_name1 = NULL;
					const char * attValue1 = "SPAATTRIB_UNIT";
					char name[MAX_FILE_NAME_CHARS] = "";
					//for getting the property unit in format like g_cm3, ft2_sec2-F etc.
					result = api_find_named_attribute( iEntity, attValue1, (ATTRIB_GEN_NAME*&)(param_attrib_name1) );
					if(param_attrib_name1 != 0)
						convertedChars = wcstombs( name,  (wchar_t *)(param_attrib_name1->value()), MAX_FILE_NAME_CHARS );
					if(convertedChars != -1)
						LOG_DEBUG("\t\t %s",name);
				}
		    }
		}
		return true;
	}
	return false;
}

//Geometric Validation Properties 
bool DumpGeomValidationProperties( ENTITY* ipEnt)
{
	ATTRIB_GEN_REAL* pGeomProp = NULL;
	
	//	Volume
	outcome result = api_find_named_attribute( ipEnt, "	SPAATTRIB_GVP_VOLUME", reinterpret_cast< ATTRIB_GEN_NAME*&>( pGeomProp ) );

	if( result.ok() == TRUE && NULL != pGeomProp)
	{
		double oGeomProp = pGeomProp->value();
		LOG_DEBUG("	SPAATTRIB_GVP_VOLUME  : {}",oGeomProp);
	}

	//	Area
	result = api_find_named_attribute( ipEnt, "SPAATTRIB_GVP_AREA ", reinterpret_cast< ATTRIB_GEN_NAME*&>( pGeomProp ) );

	if( result.ok() == TRUE && NULL != pGeomProp)
	{
		double oGeomProp = pGeomProp->value();
		LOG_DEBUG("SPAATTRIB_GVP_AREA : {}",oGeomProp);
	}

	//	Center of gravity
	result = api_find_named_attribute( ipEnt, "SPAATTRIB_GVP_CG", reinterpret_cast< ATTRIB_GEN_NAME*&>( pGeomProp ) );

	if( result.ok() == TRUE && NULL != pGeomProp)
	{
		double oGeomProp = pGeomProp->value();
		LOG_DEBUG("SPAATTRIB_GVP_CG : {}",oGeomProp);
	}

	//	Wire Length 
	result = api_find_named_attribute( ipEnt, "SPAATTRIB_GVP_LENGTH ", reinterpret_cast< ATTRIB_GEN_NAME*&>( pGeomProp ) );

	if( result.ok() == TRUE && NULL != pGeomProp)
	{
		double oGeomProp = pGeomProp->value() ;
		LOG_DEBUG("SPAATTRIB_GVP_LENGTH  : {}",oGeomProp);
	}
	return true;
}

//	SheetMetalThickness
bool DumpSheetMetalThicknessAttribute(ENTITY* iEnt)
{
	ATTRIB_GEN_REAL* pSheetMetalThickness = NULL;

	outcome result = api_find_named_attribute(iEnt, "SPAATTRIB_SHEETMETAL_THICKNESS", reinterpret_cast<ATTRIB_GEN_NAME*&>(pSheetMetalThickness));

	if (result.ok() == TRUE && NULL != pSheetMetalThickness)
	{
		double oSheetMetalThickness = pSheetMetalThickness->value();
		LOG_DEBUG("SPAATTRIB_SHEETMETAL_THICKNESS : {}", oSheetMetalThickness);
		return true;
	}
	return false;
}

void GetAttribute(ENTITY* pEnt)
{
    if (!pEnt) {
        LOG_ERROR("entity is null.") ;
        return ;
    }
    int dummyPointIndex = 0;
    ATTRIB_GEN_INTEGER* dummyPointAttrib = NULL;
    outcome	result = api_find_named_attribute(pEnt, "ATTRIB_XACIS_DUMMY_POINT_FOR_PMI", reinterpret_cast<ATTRIB_GEN_NAME*&>(dummyPointAttrib));

    if (dummyPointAttrib != NULL)
        dummyPointIndex = dummyPointAttrib->value();

    if (dummyPointIndex == 1)
    {
        return  ;
    }  
    if (is_SPACOLLECTION(pEnt))
    {
        // DumpGroupTypeAttribute(pEnt, fp);
        LOG_DEBUG("group type") ;
    }
    else
    {
        DumpNameAttribute(pEnt);
        DumpShowAttribute(pEnt);
        DumpIdAttribute(pEnt);
        DumpPNAMEAttribute(pEnt);
        DumpPIDAttribute(pEnt);
        DumpAliasAttribute(pEnt);
        DumpPlaneAttribute(pEnt);
        DumpAxisAttribute(pEnt);
        DumpColorAttribute(pEnt);
        DumpLayerNumberAttribute(pEnt);
        DumpLayerNameAttribute(pEnt);
        DumpMaterialProperty(pEnt);
        DumpGeomValidationProperties(pEnt);
        DumpSheetMetalThicknessAttribute(pEnt);
    }
}

 
}
 
 
 AMCAX_EXCHANGE_NAMESPACE_END